package br.com.spam.pipeline;

import br.com.spam.pipeline.core.PipelineSimulator;
import br.com.spam.pipeline.core.Processor;
import br.com.spam.pipeline.instruction.Instruction;
import br.com.spam.pipeline.instruction.i.ADDi;
import br.com.spam.pipeline.instruction.i.BEQ;
import br.com.spam.pipeline.instruction.i.BLE;
import br.com.spam.pipeline.instruction.i.BNE;
import br.com.spam.pipeline.instruction.i.LW;
import br.com.spam.pipeline.instruction.i.SW;
import br.com.spam.pipeline.instruction.j.JMP;
import br.com.spam.pipeline.instruction.r.ADD;
import br.com.spam.pipeline.instruction.r.MUL;
import br.com.spam.pipeline.instruction.r.NOP;
import br.com.spam.pipeline.instruction.r.SUB;

public class InstructionFactory
{
	public static Instruction recognize(String instruction, PipelineSimulator pipeline)
	{
		int id = Integer.valueOf(instruction.substring(0, 6));

		switch (id)
		{
			case 0 :
				return RInstruction(instruction, pipeline.getProcessor());
			case ADDi.ID :
				return new ADDi(instruction, pipeline.getProcessor());
			case BEQ.ID :
				return new BEQ(instruction, pipeline.getProcessor());
			case BLE.ID :
				return new BLE(instruction, pipeline.getProcessor());
			case BNE.ID :
				return new BNE(instruction, pipeline.getProcessor());
			case JMP.ID :
				return new JMP(instruction, pipeline.getProcessor());
			case LW.ID :
				return new LW(instruction, pipeline.getProcessor(), pipeline.getMemory());
			case SW.ID :
				return new SW(instruction, pipeline.getProcessor(), pipeline.getMemory());
		}
		return new NOP(pipeline.getProcessor());
	}

	private static Instruction RInstruction(String instruction, Processor processor)
	{
		int funct = Integer.valueOf(instruction.substring(26, 32));
		switch (funct)
		{
			case ADD.FUNCT :
				return new ADD(instruction, processor);
			case MUL.FUNCT :
				return new MUL(instruction, processor);
			case SUB.FUNCT :
				return new SUB(instruction, processor);
		}
		return new NOP(processor);
	}

}
